package megrez.keycloak.providers.mqtt;

import java.util.HashMap;
import java.util.Map;

import org.apache.commons.lang.builder.ReflectionToStringBuilder;
import org.keycloak.Config.Scope;

import lombok.Builder;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import megrez.keycloak.common.StringHelper;

/**
 * 配置属性
 * 
 * @author Lucky Yang
 * @since 2.6.9
 */
@Getter
@Slf4j
@Builder
public class MqttConfigProperties {
    /** 服务地址 */
    private String broker;
    /** 用户名 */
    private String username;
    /** 密码 */
    private String password;
    /** 客户端ID */
    private String clientId;

    /** 自动重新连接 */
    private boolean automaticReconnect;
    /** 清楚会话 */
    private boolean cleanSession;
    /** 连接超时，单位秒 */
    private int connectionTimeout;
    /** 保持连接, 单位秒 */
    private int keepAliveInterval;

    public static MqttConfigProperties create(Scope config) {
        final MqttConfigProperties rslt = PropertyInfo.configProperties(config);
        if (log.isDebugEnabled()) {
            log.debug(rslt.toString());
        }
        return rslt;
    }

    @Override
    public String toString() {
        return ReflectionToStringBuilder.toStringExclude(this, "password");
    }

    public Map<String, String> toMap() {
        final Map<String, String> rslt = new HashMap<>();
        rslt.put(PropertyInfo.BROKER.getCode(), this.broker);
        rslt.put(PropertyInfo.USERNAME.getCode(), this.username);
        rslt.put(PropertyInfo.CLIENT_ID.getCode(), this.clientId);
        rslt.put(PropertyInfo.AUTOMATIC_RECONNECT.getCode(), String.valueOf(this.automaticReconnect));
        rslt.put(PropertyInfo.CLEAN_SESSION.getCode(), String.valueOf(this.cleanSession));
        rslt.put(PropertyInfo.CONNECTION_TIMEOUT.getCode(), String.valueOf(this.connectionTimeout));
        rslt.put(PropertyInfo.KEEP_ALIVE_INTERVAL.getCode(), String.valueOf(this.keepAliveInterval));
        return rslt;
    }

    @Getter
    public enum PropertyInfo {
        BROKER("broker", "MQTT Broker 服务的 TCP/IP 地址", "tcp://localhost:1883"),
        USERNAME("username", "通过发送用户名和密码来进行相关的认证和授权", null),
        PASSWORD("password", "通过发送用户名和密码来进行相关的认证和授权", null),
        CLIENT_ID("clientId", "服务端使用 ClientId 识别客户端。连接服务端的每个客户端都有唯一的 ClientId", "keycloak"),
        AUTOMATIC_RECONNECT("automaticReconnect", "自动重新连接", true),
        CLEAN_SESSION("cleanSession", "客户端和服务端可以保存会话状态，以支持跨网络连接的可靠消息传输，这个标志告诉服务器这次连接是不是一个全新的连接", true),
        CONNECTION_TIMEOUT("connectionTimeout", "以秒为单位，连接超时时间", 3),
        KEEP_ALIVE_INTERVAL("keepAliveInterval", "以秒为单位的时间间隔，它是指在客户端传输完成一个控制报文的时刻到发送下一个报文的时刻，两者之间允许空闲的最大时间间隔", 60),
        ;

        private final String code;
        private final String helpText;
        private final Object defaultValue;

        private PropertyInfo(String code, String helpText, Object defaultValue) {
            this.code = code;
            this.helpText = helpText;
            this.defaultValue = defaultValue;
        }

        public String resolveConfigVar(final Scope config) {
            String value = this.defaultValue == null ? null : this.defaultValue.toString();
            if (config != null && config.get(this.code) != null) {
                value = config.get(this.code);
            } else {
                // 尝试从环境变量中读取配置信息，如: MQTT_BROKER:
                String envVariableName = "MQTT_" + StringHelper.camelCaseToUnderscore(this.code);
                String env = System.getenv(envVariableName);
                if (env != null) {
                    value = env;
                }
            }
            return value;
        }

        /**
         * 读取参数信息
         * 
         * @param config
         * @return
         */
        public static MqttConfigProperties configProperties(final Scope config) {
            final String broker = BROKER.resolveConfigVar(config);
            final String username = USERNAME.resolveConfigVar(config);
            final String password = PASSWORD.resolveConfigVar(config);
            final boolean automaticReconnect = Boolean
                    .parseBoolean(AUTOMATIC_RECONNECT.resolveConfigVar(config));
            final boolean cleanSession = Boolean.parseBoolean(CLEAN_SESSION.resolveConfigVar(config));
            final int connectionTimeout = Integer.parseInt(CONNECTION_TIMEOUT.resolveConfigVar(config));
            final int keepAliveInterval = Integer.parseInt(KEEP_ALIVE_INTERVAL.resolveConfigVar(config));
            final String clientId = CLIENT_ID.resolveConfigVar(config);

            return new MqttConfigProperties(broker, username, password, clientId,
                    automaticReconnect, cleanSession, connectionTimeout, keepAliveInterval);
        }
    }
}
